package com.fp.m7.dao;

import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Order;
import org.springframework.data.mongodb.core.query.Query;

import com.fp.m7.model.Account;
import com.fp.m7.model.Comment;
import com.fp.m7.model.Follow;
import com.fp.m7.repository.CommentRepository;
import com.google.common.collect.Lists;

public class CommentDaoImpl extends BaseDaoImpl<Comment, CommentRepository>
		implements CommentDao {

	@Override
	public List<Comment> findUsersLatestComments(Account user, int maxPerPage,
			int pageNo) {
		if (maxPerPage == 0) {
			return Lists.newArrayList();
		} else if (maxPerPage < 0 || pageNo < 0) {
			throw new IllegalArgumentException("Neither maxPageSize nor pageNo can be negative.");
		}
		Query query = Query.query(Criteria.where("authorId").is(user.getId()))
				.limit(maxPerPage).skip(pageNo * maxPerPage);

		return template.find(withDescendingSort(query), Comment.class);
	}

	@Override
	public List<Comment> findUsersCommentsByDate(Account user, Date from,
			Date to) {
		Query query = Query.query(Criteria.where("authorId").is(user.getId())
				.and("date").gte(from.getTime()).lt(to.getTime()));

		return template.find(withDescendingSort(query), Comment.class);
	}

	@Override
	public List<Comment> findCommentFeedForUser(Account user, int maxPerPage,
			int pageNo) {
		
		List<Comment> comments = Lists.newArrayList();
		if (maxPerPage == 0) {
			return comments;
		} else if (maxPerPage < 0 || pageNo < 0) {
			throw new IllegalArgumentException("Neither maxPageSize nor pageNo can be negative.");
		}

		Account fromDb = template.findById(user.getId(), Account.class);
		for (Follow follow : fromDb.getFollowing()) {
			Criteria criteria = Criteria.where("authorId").is(follow.getFollowedId())
					.and("date").gte(follow.getAuditCD());
			if (follow.getAuditDD() != null) {
				criteria = criteria.lt(follow.getAuditDD());
			}
			Query query = Query.query(criteria);
			comments.addAll(template.find(query, Comment.class));
		}

		Collections.sort(comments);
		int from = pageNo * maxPerPage;
		int to = (pageNo + 1) * maxPerPage;
		from = Math.min(from, comments.size());
		to = Math.min(to, comments.size());
		return comments.subList(from, to);
	}

	@Override
	public int removeUsersComments(Account user) {
		template.remove(
				Query.query(Criteria.where("authorId").is(user.getId())),
				Comment.class);
		return 0; // FIXME ?
	}

	private Query withDescendingSort(Query query) {
		query.sort().on("date", Order.DESCENDING);
		return query;
	}

}
